#pragma once
#include <string>
#include "ImportExport.h"

namespace ja2
{
	//! Create wstring (utf-16) from utf-8.
	JA2_CORE_API std::wstring to_utf16(std::string const &Str);
	
	//! Convert wstring (utf-16) to utf-8
	JA2_CORE_API std::string to_utf8(std::wstring const &Str);
} /*ja2*/

#if 0
//! Simple UTF8 wrapper; uses utf8 implementation from http://utfcpp.sourceforge.net/
class utf8string
{
	// Typedefs
private:
	typedef std::wstring str_t;
	typedef str_t::value_type char_t;
	typedef str_t::value_type *ptr_t;
	typedef str_t::size_type size_t;

	// Attributes
private:
	//! String.
	str_t m_Str;

//	friend bool operator<(utf8string const& s1, utf8string const& s2);
	// Operation
public:
	//! Convert to utf-8.
	std::string	utf8() const;
	// Returns const reference to copy or compare string.
	std::wstring const&	c_wcs() const;
	//! Is empty.
	bool empty() const;
	//! Size.
	utf8string::size_t size() const;
private:
	//! Convert to utf-16.
	static str_t as_utf16(std::string const& str);
/*	
	////////////////////////////////////////////////////////////////////
	static bool less(const utf8string::char_t* s1, const utf8string::char_t* s2);
	static bool equal(const utf8string::char_t* s1, const utf8string::char_t* s2);
	// case sensitive
	static bool lessCase(const utf8string::char_t*  s1, const utf8string::char_t* s2);
	static bool equalCase(const utf8string::char_t* s1, const utf8string::char_t* s2);

	template<bool (*funName)(const utf8string::char_t* s1, const utf8string::char_t* s2)> 
	class Op{
	public:
		bool operator()(const utf8string& s1, const utf8string& s2) const
		{
			return funName(s1.c_str(),s2.c_str());
		}
	};
	typedef Op<utf8string::less>		Less;
	typedef Op<utf8string::lessCase>	LessCase;
	typedef Op<utf8string::equal>		Equal;
	typedef Op<utf8string::equalCase>	EqualCase;
	

	static std::string			narrow(wchar_t const* str, utf8string::size_t length);
	static utf8string::size_t	narrow(wchar_t const* src_str, utf8string::size_t src_len, char* dst_str, utf8string::size_t dst_len);
	static utf8string::size_t	narrow(std::wstring const& src, std::string& dst);
	// 
	static std::wstring			widen(char const* str, utf8string::size_t length);
	static utf8string::size_t	widen(char const* src_str, utf8string::size_t src_len, wchar_t* dst_str, utf8string::size_t dst_len);
	static utf8string::size_t	widen(std::string const& src, std::wstring& dst);
*/
	

	// Construction/Destruction
public:
	utf8string();
	utf8string(utf8string &&Rvalue);
	utf8string(std::string const& str);
	utf8string(std::wstring const& str);

	// Friends
public:
	friend utf8string operator+(utf8string &Str, utf8string const &Str);
	friend utf8string &operator+=(utf8string &Str, utf8string const &Str);
	friend std::wstringstream& operator<<(std::wstringstream &Out, utf8string const &Str);
};

inline utf8string::utf8string()
{
}

inline utf8string::utf8string(utf8string &&Rvalue)
	: m_Str(std::move(Rvalue.m_Str))
{
}

inline utf8string::utf8string(std::string const &Str)
	: m_Str(as_utf16(Str))
{
}

inline utf8string::utf8string(std::wstring const &Str)
	: m_Str(Str)
{	
}

inline utf8string::str_t utf8string::as_utf16(std::string const& str)
{
	str_t out;
	try
	{
		utf8::utf8to16(str.begin(), str.end(), std::back_inserter(out));
	}
	catch(utf8::invalid_utf8 const &e)
	{
		throw InvalidUtf8((boost::format("%1%: %X") % e.what() % e.utf8_octet()).str());
	}

	return out;
}

inline std::string utf8string::utf8()
{
	std::string out;
	utf8::utf16to8(m_Str.begin(), m_Str.end(), std::back_inserter(out));
	return out;
}

inline bool utf8string::empty() const
{
	return m_Str.empty();
}

inline std::wstring const &utf8string::c_wcs() const
{
	return m_Str;
}

inline utf8string::size_t utf8string::size() const
{
	return m_Str.size();
}

inline utf8string operator+(utf8string &Source, utf8string const &Str)
{
	return utf8string(Source.m_Str + Str.m_Str);
}

inline utf8string &operator+=(utf8string &Source, utf8string const &Str)
{
	Source.m_Str += str.m_Str;
	return m_Str;
}

inline std::wstringstream& operator<<(std::wstringstream &Out, utf8string const &Str)
{
	Out << Str.m_str;
	return Out;
}
#endif
/*
bool operator<(utf8string const& s1, utf8string const& s2);

VFS_API std::wstringstream& operator<<(std::wstringstream& out, utf8string::str_t const& str);
VFS_API std::wstringstream& operator<<(std::wstringstream& out, const utf8string::char_t* str);

// explicit compare
namespace StrCmp
{
	// case IN-sensitive
	VFS_API bool Equal(const char* s1, const char* s2);
	VFS_API bool Equal(std::string const& s1, std::string const& s2);
	VFS_API bool Equal(std::string const& s1, const char* s2);
	VFS_API bool Equal(const char* s1, std::string const& s2);
	//
	VFS_API bool Equal(const wchar_t* s1, const wchar_t* s2);
	VFS_API bool Equal(std::wstring const& s1, std::wstring const& s2);
	VFS_API bool Equal(std::wstring const& s1, const wchar_t* s2);
	VFS_API bool Equal(const wchar_t* s1, std::wstring const& s2);
	//
	VFS_API bool Equal(utf8string const& s1, utf8string const& s2);
	VFS_API bool Equal(utf8string const& s1, std::wstring const& s2);
	VFS_API bool Equal(std::wstring const& s1, utf8string const& s2);
	VFS_API bool Equal(utf8string const& s1, const wchar_t* s2);
	VFS_API bool Equal(const wchar_t* s1, utf8string const& s2);
	// case Sensitive
	VFS_API bool EqualCase(const char* s1, const char* s2);
	VFS_API bool EqualCase(std::string const& s1, std::string const& s2);
	VFS_API bool EqualCase(std::string const& s1, const char* s2);
	VFS_API bool EqualCase(const char* s1, std::string const& s2);
	//
	VFS_API bool EqualCase(const wchar_t* s1, const wchar_t* s2);
	VFS_API bool EqualCase(std::wstring const& s1, std::wstring const& s2);
	VFS_API bool EqualCase(std::wstring const& s1, const wchar_t* s2);
	VFS_API bool EqualCase(const wchar_t* s1, std::wstring const& s2);
	//
	VFS_API bool EqualCase(utf8string const& s1, utf8string const& s2);
	VFS_API bool EqualCase(utf8string const& s1, std::wstring const& s2);
	VFS_API bool EqualCase(std::wstring const& s1, utf8string const& s2);
	VFS_API bool EqualCase(utf8string const& s1, const wchar_t* s2);
	VFS_API bool EqualCase(const wchar_t* s1, utf8string const& s2);
}
*/
